Tutorial: Using diary objects

Using diary objects

In this tutorial, we will take a tour of functionality available in diary objects. This tutorial assumes a basic understanding of HTML and JavaScript.

This page includes several examples that you can try in the developer console. Open it now by pressing ctrl + shift + C (Apple + shift + C on Mac), and clicking Console. You should be able to use the pre-loaded diary and other_diary objects right away.

Loading files with the high-level API

Browsers will normally use the high-level API, which automatically loads dependencies and manages some extra functionality. This page uses the high-level API with this HTML:

<input type="file" id="diary-input">

... and this JavaScript:

var diary_loader = new DiaryLoader(

    function(diary,source) { // called when a new diary is loaded

        window.high_level_diary = diary;

        console.log(
          "diary avialable in `high_level_diary`, loaded from " + source + ":\n",
          window.high_level_diary
        );

    },

    function(raw,source) { // called when a diary cannot be loaded
        console.log( "Failed to load", raw, source );
    }

);

document.getElementById("diary-input")
    .addEventListener( "change", event => diary_loader.load(event) );

Try loading a diary with the file input:

When you load data with the input, the callback will be called with the event as the source parameter. The source can also be hash or hashChange - see outputting diaries below for details. Future versions of the library will probably add more types of source (e.g. localStorage).

Loading files with the low-level API

Node.JS scripts will normally use the low-level API, which avoids features that only exist in browsers. The low-level API is rarely useful in the browser, but you can try it out by typing this in the console:

var diary_input_clone = Object.assign({},diary_input_object);
new_sleep_diary(diary_input_clone);

The diary_input_object variable was created for this page. Normally you would write your own code to construct an object that resembled one of these:

{
  "file_format": "string",
  "contents": ...
}

or:

{
  "file_format": "archive",
  "contents": {
    "filename 1": ...,
    "filename 2": ...,
    ...
  }
}

It doesn't matter how you construct these variables, but most people will want to use the fs module to load files and JSZip or JSZip-sync to unpack archives.

Using the Standard format

Diaries are normally represented in the diary's native format. Different formats often share common members, but new formats can be added at any time and could behave differently. So unless you need to use features specific to a single format, you would normally convert your data to Standard format for processing. Run these commands in the console:

var diary_standard = diary.to("Standard");
var other_diary_standard = other_diary.to("Standard");
console.log( diary_standard, other_diary_standard );

The Standard format represents common sleep diary features in a standard way, so you can compare diaries that were created with different programs.

Converting between formats

You can also convert data to other formats:

var diary_sleepmeter = diary.to("Sleepmeter")
var other_diary_sleep_as_android = other_diary.to("SleepAsAndroid")
console.log( diary_sleepmeter, other_diary_sleep_as_android );

Most formats convert data to Standard format internally, then convert that to their internal format. If you look carefully at the results above, you can see that some information has been lost in the conversion.

Merging diaries

Diaries can be merged together:

var diary_merged = diary.merge(other_diary)
console.log( diary_merged );

This will merge the contents of diary into other_diary, automatically converting the data to other_diary's native format.

Outputting diaries

There are two ways to generate output data for diaries:

diary.to_async("url").then(function(diary_url) {
  console.log( diary_url );
});

This creates a URL-encoded string based on the diary data. The high-level API will automatically load this string if it sees it in a URL hash:

diary.to_async("url").then(function(diary_url) {
  location.hash = '#' + diary_url;
  location.reload(); // setting "location.hash" doesn't trigger a hashChange
});

You can also create an output version of the diary:

diary.to_async("output").then( function(output) {
  console.log(output);
});

These examples use to_async() to create an output without blocking other activity. Although some formats can create an output with to(), you should prefer to_async() for maximum compatibility.